package com.ideal.frame.sys.service;

import cn.hutool.core.lang.Assert;
import com.ideal.frame.jpa.DSLPageRequest;
import com.ideal.frame.jpa.JpaRepositoryImpl;
import com.ideal.frame.sys.entity.*;
import com.ideal.frame.sys.form.search.RoleSearchForm;
import com.ideal.frame.util.UserUtils;
import com.querydsl.core.dml.UpdateClause;
import com.querydsl.jpa.impl.JPAQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @Author: jin
 * @CreateTime: 2019-11-04 10:22
 * @Description: 角色管理
 */
@Service
@Transactional
public class SysRoleService {

    @PersistenceContext
    protected EntityManager entityManager;

    private JpaRepositoryImpl<SysRole, Long> roleRepo;
    private JpaRepositoryImpl<SysUserRole, Long> userRoleRepo;
    private JpaRepositoryImpl<SysRoleMenu, Long> roleMenuRepo;

    QSysRole qSysRole = QSysRole.sysRole;
    QSysUserRole qSysUserRole = QSysUserRole.sysUserRole;
    QSysRoleMenu qSysRoleMenu = QSysRoleMenu.sysRoleMenu;

    @PostConstruct
    public void initRepo() {
        this.roleRepo = new JpaRepositoryImpl<>(SysRole.class, entityManager);
        this.userRoleRepo = new JpaRepositoryImpl<>(SysUserRole.class, entityManager);
        this.roleMenuRepo = new JpaRepositoryImpl<>(SysRoleMenu.class, entityManager);
    }

    /**
     * 根据用户id获取所有角色
     *
     * @param userId
     * @return
     */
    public List<SysRole> getRolesByUserId(Long userId) {
        return userRoleRepo.select(qSysUserRole.sysRole).from(qSysUserRole)
                .where(qSysUserRole.sysUser.id.eq(userId)).fetch();
    }

    /**
     * 获取所有的角色列表
     *
     * @return
     */
    public List<SysRole> getAllRoles() {
        return roleRepo.findAll(qSysRole.delFlag.isFalse());
    }

    /**
     * 根据查询条件获取角色列表
     *
     * @param queryForm
     * @return
     */
    public Page<SysRole> getRoleList(RoleSearchForm queryForm) {
        DSLPageRequest pageRequest = queryForm.asDslPageRequest();
        if (StringUtils.isNoneEmpty(queryForm.getName())) {
            pageRequest.addWhere(qSysRole.name.like("%" + queryForm.getName() + "%"));
        }
        pageRequest.addWhere(qSysRole.delFlag.isFalse());
        return roleRepo.findAll(pageRequest);
    }

    /**
     * 根据名称获取角色信息
     *
     * @param name
     * @return
     */
    public SysRole getByName(String name) {
        Optional<SysRole> optional = roleRepo.findOne(qSysRole.name.eq(name));
        return optional.isPresent() ? optional.get() : null;
    }

    /**
     * 根据id获取角色信息
     *
     * @param id
     * @return
     */
    public SysRole getById(Long id) {
        SysRole role = roleRepo.getOne(id);
        // 获取菜单信息
        List<SysRoleMenu> menus = roleMenuRepo.findAll(qSysRoleMenu.sysRole.id.eq(id));
        List<Long> ids = new ArrayList<>();
        menus.forEach(t -> ids.add(t.getSysMenu().getId()));
        role.setMenuIds(ids);
        return role;
    }

    /**
     * 保存
     *
     * @param role
     */
    @Transactional
    public void save(SysRole role) {
        // 检查角色名称是否已经存在
        SysRole sysRole = getByName(role.getName());
        Assert.isFalse(sysRole != null && !sysRole.isDelFlag() && sysRole.getId() != role.getId(), "当前角色已存在");
        // 判断是新增操作
        if (sysRole != null && sysRole.isDelFlag() && role.getId() == null) {
            role.setCreateTime(new Date());
            role.setId(sysRole.getId());
        } else if (sysRole != null && sysRole.isDelFlag() && role.getId() != null) {
            roleRepo.deleteById(sysRole.getId());
        }
        // 判断当前是否有id信息，如果没有添加创建时间
        if (role.getId() == null) role.setCreateTime(new Date());
        role.setModifyTime(new Date());
        role.setDelFlag(false);
        SysRole result = roleRepo.save(role);

        // 保存菜单关联信息
        roleMenuRepo.deleteInBatch(roleMenuRepo.findAll(qSysRoleMenu.sysRole.id.eq(result.getId())));

        List<SysRoleMenu> menus = new ArrayList<>();
        role.getMenuIds().forEach(t -> {
            SysRoleMenu menu = new SysRoleMenu();
            SysMenu sysMenu = new SysMenu();
            sysMenu.setId(t);
            menu.setSysMenu(sysMenu);
            menu.setSysRole(result);
            menus.add(menu);
        });
        roleMenuRepo.saveAll(menus);
    }

    /**
     * 删除
     *
     * @param ids
     */
    public void delRole(List<Long> ids) {
        //先删除rolemenu，然后删除role
        QSysRoleMenu qSysRoleMenu = QSysRoleMenu.sysRoleMenu;
        roleMenuRepo.delete(qSysRoleMenu).where(qSysRoleMenu.sysRole.id.in(ids)).execute();

        UpdateClause updateClause = roleRepo.updateClause();
        updateClause.set(qSysRole.delFlag, true);
        updateClause.set(qSysRole.modifyTime, new Date());
        updateClause.set(qSysRole.modifyUser, UserUtils.getCurrentUser().getId());
        updateClause.where(qSysRole.id.in(ids));
        updateClause.execute();
    }
}
